﻿using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Drawing.Diagrams;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using ModelContextProtocol;
using ModelContextProtocol.Server;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PInvoke;
using SendGrid.Helpers.Mail;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace WeatherMcpServer
{
    [McpServerToolType]    //MCP 协议标记特性，表明这是一个 MCP 服务端工具类，用于注册到 MCP 服务器，供客户端调用。
    public class WeatherTool
    {
        private readonly HttpClient _httpClient;
        private const string ApiKey = "ed330f13dd09445fbbe53312250109"; // 注意：实际使用需替换为有效密钥
        private readonly ILogger<WeatherTool> _logger;
        public WeatherTool(IHttpClientFactory httpClientFactory)
        {
            _httpClient = httpClientFactory.CreateClient();
        }

        [McpServerTool(Name = "get-forecast")]
        [Description("获取指定坐标的详细天气预报")]
        public async Task<string> GetForecastAsync(
    [Description("纬度")] double latitude,
    [Description("经度")] double longitude)
        {
            // 扩展API请求参数，获取更多气象数据
            var url = $"https://api.weatherapi.com/v1/forecast.json?key={ApiKey}&q={latitude},{longitude}&days=3&aqi=yes&alerts=no";
            try
            {
                var response = await _httpClient.GetFromJsonAsync<WeatherData>(url);
                return FormatForecast(response);
            }
            // 捕获请求过于频繁的异常（HTTP状态码429）
            catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
            {
                return "请求过于频繁，请稍后重试";
            }
            // 捕获其他HttpRequestException异常
            catch (HttpRequestException ex)
            {
                _logger.LogError(ex, "天气查询HTTP请求失败");
                return "服务暂时不可用";
            }
            catch (JsonException ex)
            {
                _logger.LogError(ex, "天气数据解析错误");
                return "数据解析错误";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "天气查询发生未知错误");
                return "服务暂时不可用";
            }
        }

        private static string FormatForecast(WeatherData data)
        {
            if (data == null)
                return "未获取到有效天气数据";

            var sb = new StringBuilder();

            // 添加地区信息
            sb.AppendLine($"地区：{data.Location.Name}，{data.Location.Region}，{data.Location.Country}");
            sb.AppendLine($"更新时间：{data.Current.LastUpdated}");
            sb.AppendLine("-----------------------------------");

            // 当前天气信息
            sb.AppendLine("当前天气：");
            sb.AppendLine($"天气状况：{data.Current.Condition.Text}");
            sb.AppendLine($"温度：{data.Current.TempC}°C （体感：{data.Current.FeelslikeC}°C）");
            sb.AppendLine($"湿度：{data.Current.Humidity}%");
            sb.AppendLine($"风向：{data.Current.WindDir}，风速：{data.Current.WindKph} km/h");
            sb.AppendLine($"紫外线指数：{data.Current.Uv}（{GetUvDescription(data.Current.Uv)}）");

            // 空气质量信息
            if (data.Current.AirQuality != null)
            {
                sb.AppendLine($"空气质量指数：{data.Current.AirQuality.Pm25}（{GetAirQualityDescription(data.Current.AirQuality.Pm25)}）");
            }

            // 未来三天预报
            sb.AppendLine("\n-----------------------------------");
            sb.AppendLine("未来三天预报：");
            foreach (var day in data.Forecast.ForecastDay.Take(3))
            {
                sb.AppendLine($"\n{day.Date:yyyy-MM-dd}（{GetWeekday(day.Date.DayOfWeek)}）");
                sb.AppendLine($"天气状况：{day.Day.Condition.Text}");
                sb.AppendLine($"温度：最高 {day.Day.MaxTempC}°C，最低 {day.Day.MinTempC}°C");
                sb.AppendLine($"湿度：平均 {day.Day.AvgHumidity}%");
                sb.AppendLine($"风向：{day.Day.WindDir}，风速：{day.Day.MaxWindKph} km/h");
                sb.AppendLine($"紫外线指数：{day.Day.Uv}");
            }

            return sb.ToString();
        }

        // 辅助方法：获取星期几的中文描述
        private static string GetWeekday(DayOfWeek dayOfWeek)
        {
            return dayOfWeek switch
            {
                DayOfWeek.Monday => "星期一",
                DayOfWeek.Tuesday => "星期二",
                DayOfWeek.Wednesday => "星期三",
                DayOfWeek.Thursday => "星期四",
                DayOfWeek.Friday => "星期五",
                DayOfWeek.Saturday => "星期六",
                DayOfWeek.Sunday => "星期日",
                _ => ""
            };
        }

        // 辅助方法：获取紫外线指数描述
        private static string GetUvDescription(double uvIndex)
        {
            if (uvIndex <= 2) return "低 - 无需特别防护";
            if (uvIndex <= 5) return "中等 - 建议涂抹防晒霜";
            if (uvIndex <= 7) return "高 - 建议减少户外活动";
            if (uvIndex <= 10) return "很高 - 尽量避免户外活动";
            return "极高 - 禁止长时间户外活动";
        }

        // 辅助方法：获取空气质量描述
        private static string GetAirQualityDescription(double pm25)
        {
            if (pm25 <= 50) return "优";
            if (pm25 <= 100) return "良";
            if (pm25 <= 150) return "轻度污染";
            if (pm25 <= 200) return "中度污染";
            if (pm25 <= 300) return "重度污染";
            return "严重污染";
        }

        // 扩展数据模型，支持更多气象数据
        public record WeatherData(
            [property: JsonPropertyName("location")] Location Location,
            [property: JsonPropertyName("current")] Current Current,
            [property: JsonPropertyName("forecast")] Forecast Forecast
        );

        public record Location(
            [property: JsonPropertyName("name")] string Name,
            [property: JsonPropertyName("region")] string Region,
            [property: JsonPropertyName("country")] string Country
        );

        public record Current(
            [property: JsonPropertyName("temp_c")] double TempC,
            [property: JsonPropertyName("feelslike_c")] double FeelslikeC,
            [property: JsonPropertyName("humidity")] int Humidity,
            [property: JsonPropertyName("wind_kph")] double WindKph,
            [property: JsonPropertyName("wind_dir")] string WindDir,
            [property: JsonPropertyName("uv")] double Uv,
            [property: JsonPropertyName("condition")] Condition Condition,
            [property: JsonPropertyName("last_updated")] string LastUpdated,
            [property: JsonPropertyName("air_quality")] AirQuality AirQuality
        );

        public record Condition(
            [property: JsonPropertyName("text")] string Text
        );

        public record AirQuality(
            [property: JsonPropertyName("pm2_5")] double Pm25
        );

        public record Forecast(
            [property: JsonPropertyName("forecastday")] List<ForecastDay> ForecastDay
        );

        public record ForecastDay(
            [property: JsonPropertyName("date")] DateTime Date,
            [property: JsonPropertyName("day")] DayData Day
        );

        public record DayData(
            [property: JsonPropertyName("maxtemp_c")] double MaxTempC,
            [property: JsonPropertyName("mintemp_c")] double MinTempC,
            [property: JsonPropertyName("avghumidity")] double AvgHumidity,
            [property: JsonPropertyName("maxwind_kph")] double MaxWindKph,
            [property: JsonPropertyName("wind_dir")] string WindDir,
            [property: JsonPropertyName("uv")] double Uv,
            [property: JsonPropertyName("condition")] Condition Condition
        );



        [McpServerTool(Name = "batch-query")]
        [Description("批量获取多个坐标的天气预报")]
        public async Task<IEnumerable<string>> BatchQueryAsync(
        [Description("坐标列表（格式：纬度1,经度1|纬度2,经度2，例如：39.9,116.4|31.2,121.4）")]
        string coordinateStr)
        {
            // 1. 解析输入的字符串为坐标列表
            var coordinates = ParseCoordinates(coordinateStr);
            if (!coordinates.Any())
            {
                return new List<string> { "无效的坐标格式，请使用正确格式：纬度,经度|纬度,经度" };
            }

            // 2. 限制最大查询数量（避免接口超限）
            if (coordinates.Count > 10)
            {
                return new List<string> { "最多支持同时查询10个坐标" };
            }

            // 3. 执行批量查询
            var tasks = coordinates.Select(c => GetForecastAsync(c.Lat, c.Lon));
            return await Task.WhenAll(tasks);
        }

        // 解析坐标字符串的辅助方法
        private List<Coordinate> ParseCoordinates(string coordinateStr)
        {
            var result = new List<Coordinate>();
            if (string.IsNullOrWhiteSpace(coordinateStr))
                return result;

            // 按 | 分割多个坐标
            var coordinateParts = coordinateStr.Split('|', StringSplitOptions.RemoveEmptyEntries);
            foreach (var part in coordinateParts)
            {
                // 按 , 分割纬度和经度
                var latLon = part.Split(',', StringSplitOptions.RemoveEmptyEntries);
                if (latLon.Length == 2
                    && double.TryParse(latLon[0], out double lat)
                    && double.TryParse(latLon[1], out double lon)
                    && lat >= -90 && lat <= 90 // 验证纬度范围
                    && lon >= -180 && lon <= 180) // 验证经度范围
                {
                    result.Add(new Coordinate(lat, lon));
                }
            }
            return result;
        }

        public record Coordinate(double Lat, double Lon);




    }
}
